/*
 *
 *      Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: lengleng (wangiegie@gmail.com)
 *
 */

package com.sky.business.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.plugin.excel.annotation.RequestExcel;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import com.sky.admin.api.dto.UserDTO;
import com.sky.admin.api.dto.UserInfo;
import com.sky.admin.api.entity.SysRole;
import com.sky.admin.api.entity.SysUser;
import com.sky.admin.api.vo.PageVo;
import com.sky.admin.api.vo.UserExcelVO;
import com.sky.admin.api.vo.UserVO;
import com.sky.admin.service.SysMobileService;
import com.sky.admin.service.SysRoleService;
import com.sky.admin.service.SysUserService;
import com.sky.common.core.constant.CommonConstants;
import com.sky.common.core.exception.ErrorCodes;
import com.sky.common.core.util.MsgUtils;
import com.sky.common.core.util.R;
import com.sky.common.log.annotation.SysLog;
import com.sky.common.security.annotation.Inner;
import com.sky.common.security.service.PigUser;
import com.sky.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lengleng
 * @date 2018/12/16
 */
@RestController
@AllArgsConstructor
@Tag(description = "user", name = "用户管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysUserController {

  private final SysUserService userService;

  private final SysRoleService sysRoleService;

  private final SysMobileService mobileService;

  /**
   * 获取指定用户全部信息
   *
   * @return 用户信息
   */
  @Inner
  @GetMapping("/user/info/query")
  @Hidden
  public R<UserInfo> info(@RequestParam(required = false) String username,
      @RequestParam(required = false) String phone) {
    SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda()
        .eq(StrUtil.isNotBlank(username), SysUser::getUsername, username)
        .eq(StrUtil.isNotBlank(phone), SysUser::getPhone, phone));
    if (user == null) {
      return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
    }
    return R.ok(userService.findUserInfo(user));
  }

  /**
   * 获取当前用户全部信息
   *
   * @return 用户信息
   */
  @GetMapping("/user/info")
  @Operation(summary = "获取当前用户全部信息", description = "获取当前用户全部信息")
  public R<UserInfo> info() {
    String username = SecurityUtils.getUser().getUsername();
    SysUser user = userService.getOne(
        Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
    if (user == null) {
      return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
    }
    return R.ok(userService.findUserInfoNew(user));
  }

  /**
   * 通过ID查询用户信息
   *
   * @param id ID
   * @return 用户信息
   */
  @GetMapping("/user/details/{id}")
  @Operation(summary = "查询用户", description = "根据ID查询用户")
  public R<UserVO> user(@PathVariable Long id) {
    return R.ok(userService.selectUserVoById(id));
  }

  /**
   * 查询用户信息
   *
   * @param query 查询条件
   * @return 不为空返回用户名
   */
  @Inner(value = false)
  @GetMapping("/user/details")
  @Hidden
  public R<String> getDetails(@ParameterObject SysUser query) {
    SysUser sysUser = userService.getOne(Wrappers.query(query), false);
    return R.ok(sysUser == null ? null : CommonConstants.SUCCESS);
  }

  /**
   * 删除用户信息
   *
   * @return R
   */
  @SysLog("删除用户信息")
  @DeleteMapping("/user/{userId}")
  @Operation(summary = "删除用户", description = "根据ID删除用户")
  public R<Boolean> userDel(@PathVariable Integer userId) {
    return R.ok(userService.removeById(userId));
  }

  /**
   * 添加用户
   *
   * @param userDto 用户信息
   * @return success/false
   */
  @SysLog("添加用户")
  @PostMapping("/user")
  @Operation(summary = "添加用户", description = "添加用户")
  public R<Boolean> user(@RequestBody UserDTO userDto) {
    return R.ok(userService.saveUser(userDto));
  }

  /**
   * 更新用户信息
   *
   * @param userDto 用户信息
   * @return R
   */
  @SysLog("更新用户信息")
  @PutMapping("/user")
  @Operation(summary = "更新用户", description = "更新用户")
  public R<Boolean> updateUser(@Valid @RequestBody UserDTO userDto) {
    return R.ok(userService.updateUser(userDto));
  }

  /**
   * 分页查询用户
   *
   * @param page     参数集
   * @param username 查询参数列表
   * @return 用户集合
   */
  @GetMapping("/user/page")
  @Operation(summary = "用户分页查询", description = "用户分页查询")
  public R<IPage<UserVO>> getUserPage(@ParameterObject PageVo page,
      @RequestParam(required = false) String username) {
    return R.ok(userService.getUsersWithRolePage(page, username));
  }

  /**
   * 修改个人信息
   *
   * @param userDto userDto
   * @return success/false
   */
  @SysLog("修改个人信息")
  @PutMapping("/user/edit")
  @Hidden
  public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
    return userService.updateUserInfo(userDto);
  }

  /**
   * 导出excel 表格
   *
   * @param userDTO 查询条件
   * @return
   */
  @ResponseExcel
  @GetMapping("/user/export")
  @Hidden
  public List export(UserDTO userDTO) {
    return userService.listUser(userDTO);
  }

  /**
   * 导入用户
   *
   * @param excelVOList   用户列表
   * @param bindingResult 错误信息列表
   * @return R
   */
  @PostMapping("/user/import")
  @Hidden
  public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
    return userService.importUser(excelVOList, bindingResult);
  }

  /**
   * 锁定指定用户
   *
   * @param username 用户名
   * @return R
   */
  @Inner
  @PutMapping("/user/lock/{username}")
  @Hidden
  public R lockUser(@PathVariable String username) {
    return userService.lockUser(username);
  }

  @PutMapping("/user/password")
  @SysLog("修改个人密码")
  @Operation(summary = "用户密码修改", description = "用户密码修改")
  public R<Boolean> passwordChange(@RequestBody UserDTO userDto) {
    String username = SecurityUtils.getUser().getUsername();
    userDto.setUsername(username);
    return R.ok(userService.changePassword(userDto));
  }

  @GetMapping("/role/list")
  @Operation(summary = "角色列表查询", description = "角色列表查询")
  public R<List<SysRole>> getRoleList() {
    return R.ok(sysRoleService.list(Wrappers.<SysRole>query().lambda()
        .select(SysRole::getRoleId, SysRole::getRoleName, SysRole::getRoleCode)
        .eq(SysRole::getDelFlag, CommonConstants.STATUS_NORMAL).orderByAsc(SysRole::getRoleId)));
  }

  @PutMapping("/user/last/login/time")
  @Operation(summary = "Portal用户登录成功后更新上次登录时间", description = "Portal用户登录成功后更新上次登录时间")
  public R<Boolean> updateUserLastLoginTime() {
    PigUser user = SecurityUtils.getUser();
    SysUser sysUser = new SysUser();
    sysUser.setUserId(user.getId());
    return R.ok(userService.updateById(sysUser));
  }

  @Inner(value = false)
  @GetMapping("/mobile/{mobile}")
  public R<Boolean> sendSmsCode(@PathVariable String mobile) {
    return mobileService.sendSmsCode(mobile);
  }

}
